<html>
<head><meta charset="utf-8"><title>macro invocations as match arms · t-lang · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/index.html">t-lang</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html">macro invocations as match arms</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="225315526"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225315526" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225315526">(Feb 05 2021 at 15:49)</a>:</h4>
<p>I see that the grammar / compiler doesn't allow macro invocations inside of a <code>match</code>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">match</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">arm</span><span class="o">!</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span><span class="w"></span>
<span class="w">    </span><span class="n">arm</span><span class="o">!</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>Does anyone happen to know any deeper reasoning <em>why</em> this is disallowed? Is it "no one needed it"?</p>



<a name="225331989"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225331989" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225331989">(Feb 05 2021 at 17:47)</a>:</h4>
<p>I mean, <code>macro_rules</code> macros are more often disallowed than allowed.  One can't <code>struct Foo { foo!() }</code> either, <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=21b81c2f0a660dae3235225e930321f8">for example</a>.</p>
<p>Or, more directly, it's disallowed because macro_rules aren't just token insertion, and an arm isn't a pattern, expr, or item.</p>



<a name="225335674"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225335674" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225335674">(Feb 05 2021 at 18:14)</a>:</h4>
<p>In my case, it leads to code like:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">$(</span><span class="n">mirror_owned_token</span><span class="o">!</span><span class="p">(</span><span class="o">@</span><span class="n">eq_pat</span><span class="w"> </span><span class="n">s1</span><span class="w"> </span><span class="n">s2</span><span class="w"> </span><span class="cp">$v_name</span><span class="w"> </span><span class="cp">$($field</span><span class="p">)</span><span class="o">?</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"></span>
<span class="w">  </span><span class="n">mirror_owned_token</span><span class="o">!</span><span class="p">(</span><span class="o">@</span><span class="n">eq_arm</span><span class="w"> </span><span class="n">s1</span><span class="w"> </span><span class="n">s2</span><span class="w"> </span><span class="cp">$v_name</span><span class="w"> </span><span class="cp">$($field</span><span class="p">)</span><span class="o">?</span><span class="p">)</span><span class="w"> </span><span class="p">,)</span><span class="o">*</span><span class="w"></span>
</code></pre></div>
<p>Which ideally would have been</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">$(</span><span class="n">mirror_owned_token</span><span class="o">!</span><span class="p">(</span><span class="o">@</span><span class="n">eq</span><span class="w"> </span><span class="cp">$v_name</span><span class="w"> </span><span class="cp">$($field</span><span class="p">)</span><span class="o">?</span><span class="p">)</span><span class="w"> </span><span class="p">,)</span><span class="o">*</span><span class="w"></span>
</code></pre></div>



<a name="225336165"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225336165" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225336165">(Feb 05 2021 at 18:18)</a>:</h4>
<p><span class="user-mention silent" data-user-id="125270">scottmcm</span> <a href="#narrow/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms/near/225331989">said</a>:</p>
<blockquote>
<p>and an arm isn't a pattern, expr, or item.</p>
</blockquote>
<p>I'm not sure I'm following 100%; is is a hard rule that a macro can only expand to those 3 things now and forever?</p>



<a name="225341950"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225341950" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225341950">(Feb 05 2021 at 19:05)</a>:</h4>
<p>I don't know why it's those.  IIRC it also can't do things like <code>foo!() 2</code> where <code>foo!()</code> expands to <code>1 +</code>.</p>



<a name="225342146"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225342146" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225342146">(Feb 05 2021 at 19:06)</a>:</h4>
<p>This feels to me like one of those "macro_rules is what-exists-when-cutting-1.0" things, and maybe <code>macro</code>s will pick up more things, but nobody's working on those AFAIK</p>



<a name="225357314"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225357314" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225357314">(Feb 05 2021 at 21:05)</a>:</h4>
<p><span class="user-mention silent" data-user-id="116155">Jake Goulding</span> <a href="#narrow/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms/near/225336165">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="125270">scottmcm</span> <a href="#narrow/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms/near/225331989">said</a>:</p>
<blockquote>
<p>and an arm isn't a pattern, expr, or item.</p>
</blockquote>
<p>I'm not sure I'm following 100%; is is a hard rule that a macro can only expand to those 3 things now and forever?</p>
</blockquote>
<p>(and a type)</p>



<a name="225358321"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225358321" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225358321">(Feb 05 2021 at 21:12)</a>:</h4>
<p>One case that I find especially annoying are where clauses / bounds. There has actually been a recent question on URLO about it (<a href="https://users.rust-lang.org/t/way-to-combine-traits-bound-for-reference-type/55173/2?u=yandros">https://users.rust-lang.org/t/way-to-combine-traits-bound-for-reference-type/55173/2?u=yandros</a>), and "the least bad solution" for it gets quite unwieldy: for macros to somehow get "arbitrary-place expansion" capabilities one needs to use preprocessor patterns with proc-macros or callback-style macros.<br>
An example of the latter for <code>foo!() 2</code> would be:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">with_foo</span><span class="w"> </span><span class="p">{(</span><span class="w"> </span><span class="cp">$($rules</span>:<span class="nc">tt</span><span class="p">)</span><span class="o">*</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">({</span><span class="w"></span>
<span class="w">    </span><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">__emit__</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cp">$($rules</span><span class="p">)</span><span class="o">*</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="n">__emit__</span><span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">})}</span><span class="w"></span>

<span class="n">with_foo</span><span class="o">!</span><span class="w"> </span><span class="p">{(</span><span class="w"> </span><span class="cp">$($one_plus</span>:<span class="nc">tt</span><span class="p">)</span><span class="o">*</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="w"></span>
<span class="w">    </span><span class="cp">$($one_plus</span><span class="p">)</span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="w"></span>
<span class="p">)}</span><span class="w"></span>
</code></pre></div>
<ul>
<li><a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=c043d0169c39222ece60ba121c4f7b78">https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=c043d0169c39222ece60ba121c4f7b78</a></li>
</ul>



<a name="225416916"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225416916" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Nadrieril <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225416916">(Feb 06 2021 at 15:32)</a>:</h4>
<p>My feel is that macros can only emit "well-grouped things". Conceptually I can always write <code>(foo!())</code> instead of <code>foo!()</code>. I _think_ the technical phrasing is that a macro returns a single token-tree</p>



<a name="225416962"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225416962" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Nadrieril <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225416962">(Feb 06 2021 at 15:33)</a>:</h4>
<p>I think that explains the current limitations. I don't know if that could be relaxed to emit multiple token-trees, but I suspect this would allow some pretty surprising stuff</p>



<a name="225418078"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225418078" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225418078">(Feb 06 2021 at 15:58)</a>:</h4>
<p><code>(foo!())</code> does not work in item position</p>



<a name="225418093"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225418093" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225418093">(Feb 06 2021 at 15:59)</a>:</h4>
<p>There isn't really a single-token-tree limitation, but macro invocations do have to fit in the Rust AST somehow, so they need to be accomodated for in every place they should be supported</p>



<a name="225721762"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225721762" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225721762">(Feb 09 2021 at 17:03)</a>:</h4>
<p>I'm not sure why, <span class="user-mention" data-user-id="232018">@Daniel Henry-Mantilla</span>, we would jump right to " for macros to somehow get "arbitrary-place expansion" capabilities one needs to use preprocessor patterns with proc-macros or callback-style macros." Why not just expand the set of places they can be used to include where clauses?</p>



<a name="225721784"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225721784" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225721784">(Feb 09 2021 at 17:03)</a>:</h4>
<p>(Similarly match arms)</p>



<a name="225721815"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225721815" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225721815">(Feb 09 2021 at 17:03)</a>:</h4>
<p>Maybe there are strong reasons :) I can't remember</p>



<a name="225721827"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225721827" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225721827">(Feb 09 2021 at 17:03)</a>:</h4>
<p>I admit I didn't follow the link</p>



<a name="225722747"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225722747" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225722747">(Feb 09 2021 at 17:08)</a>:</h4>
<p>I also think that is likely too strong, but I believe the rule today is that the macro expansion must form a complete item, expression, or pattern (maybe there's more things?) but basically "complete things" rather than portions of the tree.</p>



<a name="225723828"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225723828" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225723828">(Feb 09 2021 at 17:15)</a>:</h4>
<p>sure but</p>



<a name="225723848"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225723848" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225723848">(Feb 09 2021 at 17:15)</a>:</h4>
<p>a where-clause is a "complete thing"</p>



<a name="225723874"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225723874" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225723874">(Feb 09 2021 at 17:15)</a>:</h4>
<p>at least as much as a "pattern" is, for example</p>



<a name="225724148"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225724148" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225724148">(Feb 09 2021 at 17:17)</a>:</h4>
<p>kind of - I guess for patterns that's true - I think of them as a bit different but I see your point. I agree that it would not be obviously bad to allow more things, though I wouldn't want to allow any token tree I think, makes for confusing code</p>



<a name="225724163"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225724163" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225724163">(Feb 09 2021 at 17:17)</a>:</h4>
<p>(maybe that's on authors though <span aria-label="shrug" class="emoji emoji-1f937" role="img" title="shrug">:shrug:</span> )</p>



<a name="225735415"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225735415" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225735415">(Feb 09 2021 at 18:32)</a>:</h4>
<p><span class="user-mention" data-user-id="116009">@nikomatsakis</span> I was speaking from a user point of view (which I guess I should have clarified, given how this is a <code>t-lang</code> stream <span aria-label="sweat smile" class="emoji emoji-1f605" role="img" title="sweat smile">:sweat_smile:</span>): for an arbitrarily-located-within-the-AST expansion, the two always-applicable patterns that "achieve" something close to it and which are within any user's reach are macro CPS and preprocessor.</p>
<p>Regarding where clauses, I would be delighted if macro calls were allowed there <span aria-label="smile" class="emoji emoji-1f642" role="img" title="smile">:smile:</span></p>



<a name="225740545"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225740545" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225740545">(Feb 09 2021 at 19:05)</a>:</h4>
<p><span class="user-mention silent" data-user-id="116122">simulacrum</span> <a href="#narrow/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms/near/225724148">said</a>:</p>
<blockquote>
<p>kind of - I guess for patterns that's true - I think of them as a bit different but I see your point. I agree that it would not be obviously bad to allow more things, though I wouldn't want to allow any token tree I think, makes for confusing code</p>
</blockquote>
<p>I agree with that</p>



<a name="225740605"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225740605" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225740605">(Feb 09 2021 at 19:05)</a>:</h4>
<p>I sort of like the model of "macros take the place of 'complete things'"</p>



<a name="225740730"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225740730" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225740730">(Feb 09 2021 at 19:06)</a>:</h4>
<p>it is also why I don't expect <code>$a * 3</code> to have issues if <code>$a = x * y</code> (i.e., there is sort of an implied parentheses)</p>



<a name="225740745"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225740745" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225740745">(Feb 09 2021 at 19:06)</a>:</h4>
<p>although I realize one is a fragment and one is not</p>



<a name="225740776"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225740776" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225740776">(Feb 09 2021 at 19:06)</a>:</h4>
<p>I guess <code>foo!() * 3</code> is a better example</p>



<a name="225740802"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225740802" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225740802">(Feb 09 2021 at 19:07)</a>:</h4>
<p>it's not just "pasting tokens"</p>



<a name="225740973"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225740973" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225740973">(Feb 09 2021 at 19:08)</a>:</h4>
<p>right; I think allowing expansion to e.g. a where clause makes sense, but expanding to e.g. <code>where A: B</code> and allowing that e.g. in <code>foo!() + C</code> with intent of <code>where A: B + C</code> I would not expect to work.</p>



<a name="225741461"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225741461" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225741461">(Feb 09 2021 at 19:11)</a>:</h4>
<p>but then the parser will have to understand that <code>fn something() a!() {}</code> is valid code, before knowing what <code>a!()</code> expands to, right?</p>



<a name="225741817"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225741817" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225741817">(Feb 09 2021 at 19:14)</a>:</h4>
<p>i guess that could work, but then a macro in that position will always have to be a where clause, and could never (in the future) be the function body for example. (e.g. <code>fn something() a!()</code> where <code>a!()</code> expands to the body (which is not accepted right now))</p>



<a name="225741882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225741882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225741882">(Feb 09 2021 at 19:14)</a>:</h4>
<p>sure; that's a good reason to potentially not allow where clauses specifically perhaps, but the point of "whole units" is the main one I was trying to make.</p>



<a name="225742107"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225742107" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225742107">(Feb 09 2021 at 19:16)</a>:</h4>
<p>one reason to not allow macros there is that, within a function, <code> fn something() a!() { code }</code> can both include and not include the code block, depending on whether the macro expands to a block, for example. So the "parens" sort of should prevent you from doing weird things like attaching to outer partial items</p>



<a name="225742116"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225742116" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225742116">(Feb 09 2021 at 19:16)</a>:</h4>
<p>yeah sure. but what i'm trying to say is that the requirement is much stronger than just 'whole units'. it should be possible to parse without expanding the macros.</p>



<a name="225742138"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225742138" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225742138">(Feb 09 2021 at 19:16)</a>:</h4>
<p>yeah, I think that's right</p>



<a name="225742772"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225742772" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225742772">(Feb 09 2021 at 19:21)</a>:</h4>
<p>so for arms that will be a bit tricky, as <code>match () { a!() =&gt; {} }</code> is already accepted. if <code>a!()</code> could also expand to a whole arm, then the parser will have to check for a  <code>=&gt;</code> or <code>|</code> after the macro to see what it should parse it as, which might make it harder to give clear errors when there's a typo.</p>



<a name="225745848"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225745848" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225745848">(Feb 09 2021 at 19:43)</a>:</h4>
<p>wouldn't it rather be <code>fn something() where a!() {}</code>? In that case it's clear that <code>a!</code> has to be a where block.</p>



<a name="225746212"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225746212" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225746212">(Feb 09 2021 at 19:45)</a>:</h4>
<p><code>where a!(): Copy</code> is already accepted though, because macros can expand to types</p>



<a name="225746949"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225746949" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225746949">(Feb 09 2021 at 19:50)</a>:</h4>
<p>What about a special syntax to state the syntax class? That would allow macros to go just about everywhere. For example <code>a!#where()</code> modulo bikeshed</p>



<a name="225747246"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225747246" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225747246">(Feb 09 2021 at 19:52)</a>:</h4>
<p>although I am sure there are some weird syntax classes, like <code>use {foo, bar, m!#use_glob()};</code></p>



<a name="225747374"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225747374" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225747374">(Feb 09 2021 at 19:53)</a>:</h4>
<p>would that really be worth it?</p>



<a name="225747454"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225747454" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225747454">(Feb 09 2021 at 19:53)</a>:</h4>
<p>it's certainly ugly enough to not be used often, but an ugly syntax for a rarely used feature seems fair to me</p>



<a name="225747655"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225747655" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225747655">(Feb 09 2021 at 19:55)</a>:</h4>
<p>I think it's better than the alternative of CPS macros, which don't respect the AST structure</p>



<a name="225747694"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225747694" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225747694">(Feb 09 2021 at 19:55)</a>:</h4>
<p>but compared to just not supporting it?</p>



<a name="225747790"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225747790" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225747790">(Feb 09 2021 at 19:56)</a>:</h4>
<p>well not supporting it just means people will find workarounds</p>



<a name="225747855"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225747855" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225747855">(Feb 09 2021 at 19:56)</a>:</h4>
<p>CPS macros such as <span class="user-mention silent" data-user-id="232018">Daniel Henry-Mantilla</span> showed above being such a workaround</p>



<a name="225748723"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225748723" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jacob Lifshay <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225748723">(Feb 09 2021 at 20:02)</a>:</h4>
<p>I think we should avoid using <code>#</code> in new syntax, since <code>quote!</code> effectively has first dibs on nearly all uses</p>



<a name="225830191"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225830191" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225830191">(Feb 10 2021 at 12:45)</a>:</h4>
<p>In the case of <code>where</code> clauses, I think macros should be able to expand to one clause, <em>or to a sequence of such clauses</em> (which implementation-wise would be a bit trickier, but would definitely handle the case of complex bounds. Unless <code>implied_bounds</code> or <code>trait_alias</code>ed were implemented, in which case the <code>library</code> could always define a single-clause equivalent).</p>
<p>But it should never "include" the <code>where</code> part:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">fn</span> <span class="nf">foo</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Ret</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span>: <span class="nc">Debug</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">library_bounds</span><span class="o">!</span><span class="p">(</span><span class="n">T</span><span class="p">),</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">library_use</span>::<span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<hr>
<p>Back to the OP, regarding <code>match</code> arms: I also find that a similar requirement to "sequence of <code>match</code> arms" may end up being needed.</p>
<p>One such example would be syntactical duck-typing:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[derive(PartialEq, Eq, SyntacticalDuckTyping)]</span><span class="w"> </span><span class="c1">// generates an `Example!` macro</span>
<span class="k">enum</span> <span class="nc">Example</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">U16</span><span class="p">(</span><span class="kt">u16</span><span class="p">),</span><span class="w"></span>
<span class="w">    </span><span class="n">U32</span><span class="p">(</span><span class="kt">u32</span><span class="p">),</span><span class="w"></span>
<span class="w">    </span><span class="c1">// more may be added in the future</span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="w"> </span><span class="n">Example</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">SENTINEL</span>: <span class="nc">Example</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Example</span>::<span class="n">U32</span><span class="p">(</span>::<span class="n">core</span>::<span class="kt">u32</span>::<span class="n">MAX</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">example</span><span class="p">(</span><span class="n">e</span>: <span class="nc">Example</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Option</span><span class="o">&lt;</span><span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">match</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">Example</span>::<span class="n">SENTINEL</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"></span>
<span class="w">        </span><span class="n">Example</span><span class="o">!</span><span class="p">(</span><span class="o">|</span><span class="n">uN</span><span class="o">|</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">uN</span><span class="p">.</span><span class="n">to_be_bytes</span><span class="p">().</span><span class="n">to_vec</span><span class="p">())),</span><span class="w"></span>
<span class="w">        </span><span class="cm">/* expanding to:</span>
<span class="cm">            Example::U16(uN) =&gt; Some(uN.to_be_bytes().to_vec()),</span>
<span class="cm">            Example::U32(uN) =&gt; Some(uN.to_be_bytes().to_vec()),</span>
<span class="cm">        … */</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>So we are no longer in the realm of "a macro call matches a 'single AST thing'" (although for macros expanding to statements this was already the case <span aria-label="thinking" class="emoji emoji-1f914" role="img" title="thinking">:thinking:</span> so it may not be that tricky to implement)</p>
<p><span class="user-mention silent" data-user-id="310399">Mara</span> <a href="#narrow/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms/near/225742772">said</a>:</p>
<blockquote>
<p>so for arms that will be a bit tricky, as <code>match () { a!() =&gt; {} }</code> is already accepted. if <code>a!()</code> could also expand to a whole arm, then the parser will have to check for a  <code>=&gt;</code> or <code>|</code> after the macro to see what it should parse it as, which might make it harder to give clear errors when there's a typo.</p>
</blockquote>
<p>Assuming a typo of the form:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">match</span><span class="w"> </span><span class="n">scrutinee</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// typo: using `,` instead of `|`</span>
<span class="w">    </span><span class="n">expands_to_a_pattern</span><span class="o">!</span><span class="p">(),</span><span class="w"> </span><span class="n">SomeOtherPattern</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{},</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>The current error message, with macros not being allowed to expand to a full match arm, is:</p>
<div class="codehilite" data-code-language="Text only"><pre><span></span><code>error: unexpected `,` in pattern
  --&gt; src/main.rs:13:36
   |
13 |             expands_to_a_pattern!(), None =&gt; {},
   |                                    ^
   |
</code></pre></div>
<p>I could imagine the error message now becoming (assuming the pattern is, for instance, <code>Some(_)</code>):</p>
<div class="codehilite" data-code-language="Text only"><pre><span></span><code>error: expected match arm(s), found `Some(_)`  --&gt; src/main.rs:13:38
   |
13 |             expands_to_a_pattern!(), None =&gt; {},
                 ^^^^^^^^^^^^^^^^^^^^^^^
</code></pre></div>
<p>I don't really know how these diagnostics work, but when the input to an expected match arm matches the syntax of a pattern, the error message could then be enhanced with suggestions in that regard (taken from the (great!) suggestions in current Rust):</p>
<div class="codehilite" data-code-language="Text only"><pre><span></span><code>error: expected match arm(s), found `Some(_)`  --&gt; src/main.rs:13:38
   |
13 |             expands_to_a_pattern!(), None =&gt; {},
                 ^^^^^^^^^^^^^^^^^^^^^^^
help: if you intended to use a pattern, try adding parentheses to match on a tuple...
   |
13 |             (expands_to_a_pattern!(), None) =&gt; {},
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: ...or a vertical bar to match on multiple alternatives
   |
13 |             expands_to_a_pattern!() | None =&gt; {},
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
</code></pre></div>



<a name="225836071"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225836071" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225836071">(Feb 10 2021 at 13:36)</a>:</h4>
<p>yeah it could work. but we'll need to be careful not to paint ourselves into a corner here. for example, <code>type = type</code> is already parsed as a bound in where clauses, and maybe in the future we'll have something like <code>const X: i32 where ... = 1;</code>. then <code>const X: i32 where a!() = Thing</code> will be hard to parse without knowing if <code>a!()</code> expands to <code>type</code> or <code>type = type</code>. this specific example is probably unlikely to happen, but in general it's pretty hard to see how allowing macros to stand for different things in the same place might end up being a problem in the future.</p>



<a name="225836260"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225836260" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225836260">(Feb 10 2021 at 13:38)</a>:</h4>
<p>for the <code>match</code> arm situation, it'd mean that we can never start accepting <code>match (1, 2) { 1, 2 =&gt; .. }</code> even if we wanted to. this might be fine. but it's hard to list all the future things we're making impossible by allowing full match arm macros</p>



<a name="225877829"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225877829" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225877829">(Feb 10 2021 at 17:42)</a>:</h4>
<p>That last thing might impact the proposal on never patterns, i.e.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">match</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="p">(</span><span class="nb">Err</span><span class="p">(</span><span class="o">!</span><span class="p">),</span><span class="w"> </span><span class="n">_</span><span class="p">),</span><span class="w"></span>
<span class="w">    </span><span class="p">(</span><span class="nb">Ok</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="225878481"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225878481" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225878481">(Feb 10 2021 at 17:46)</a>:</h4>
<p>I can imagine this general kind of problem being solved at the compiler level by keeping track of macro calls whose syntax class isn't completely resolved; this may require some backtracking based on tokens that follow the macro call.</p>



<a name="225878948"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225878948" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225878948">(Feb 10 2021 at 17:48)</a>:</h4>
<p><span class="user-mention silent" data-user-id="310399">Mara</span> <a href="#narrow/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms/near/225742772">said</a>:</p>
<blockquote>
<p>so for arms that will be a bit tricky, as <code>match () { a!() =&gt; {} }</code> is already accepted. if <code>a!()</code> could also expand to a whole arm, then the parser will have to check for a  <code>=&gt;</code> or <code>|</code> after the macro to see what it should parse it as, which might make it harder to give clear errors when there's a typo.</p>
</blockquote>
<p>it's not particularly hard to look ahead and see what comes next</p>



<a name="225879002"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225879002" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225879002">(Feb 10 2021 at 17:49)</a>:</h4>
<p>I agree with the constraint</p>



<a name="225879033"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225879033" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225879033">(Feb 10 2021 at 17:49)</a>:</h4>
<p>it's just that it can be satisfied in many cases</p>



<a name="225888288"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225888288" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225888288">(Feb 10 2021 at 18:50)</a>:</h4>
<p>Aside-ish:<br>
@mara good point; the whole <code>where</code> situation not requiring an extra disambiguating scope can be annoying. Would clause trees make sense in order to feature a completely unambiguous syntax? Like:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">where</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span>: <span class="nc">Trait</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">U</span><span class="w"> </span>: <span class="nb">Send</span><span class="p">,</span><span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<ul>
<li>(or with <code>[ … ]</code> for the delimiter, may be less weird when dealing with <code>where</code> clauses for a <code>struct</code>).</li>
</ul>
<p>That way <code>const X: T where a!() = () = ();</code> could be given the parsing of <code>a!() is a type</code>, and for those wanting the other interpretation (<code>a!()</code> being a clause (tree)), an explicit trailing comma or braces for a clause tree would be useful.</p>
<p>I mention clause trees since (on top of solving the question of "expanding to multiple clauses), it also crossed my mind when writing high-order bounds:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="k">for</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">F</span><span class="w"> </span>: <span class="nb">FnOnce</span><span class="o">&lt;</span><span class="p">(</span><span class="o">&amp;'</span><span class="na">a</span><span class="w"> </span><span class="p">(),)</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w">       </span><span class="o">&lt;</span><span class="n">F</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nb">FnOnce</span><span class="o">&lt;</span><span class="p">(</span><span class="o">&amp;'</span><span class="na">a</span><span class="w"> </span><span class="p">(),)</span><span class="o">&gt;&gt;</span>::<span class="n">Output</span><span class="w"> </span>: <span class="o">'</span><span class="na">a</span> <span class="o">+</span><span class="w"> </span><span class="n">Future</span><span class="o">&lt;</span><span class="n">Output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">},</span><span class="w"></span>
</code></pre></div>
<p>Not only would that be a bit more lightweight to write than typing twice the <code>for</code> quantification, it could also maybe help avoid the bugs that we currently have with such higher-order bounds?</p>
<hr>
<p><span class="user-mention silent" data-user-id="271719">Mario Carneiro</span> <a href="#narrow/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms/near/225878481">said</a>:</p>
<blockquote>
<p>I can imagine this general kind of problem being solved at the compiler level by keeping track of macro calls whose syntax class isn't completely resolved; this may require some backtracking based on tokens that follow the macro call.</p>
</blockquote>
<p>I  don't think that going down that road would be worth it; I'm pretty sure that being able to know the expected AST kind of a macro call before expansion is a very nice feature that compiler devs will want to maintain. That being said, regarding the potential new syntax for never patterns (thanks for pointing that out), we could have a "dummy" / "transparent" wrapping (<em>à la</em> <code>Stmt::Item</code>) from a match arm to a pattern: by allowing match arms not to necessarily have a <code>=&gt; &lt;expr&gt;</code> RHS, I'd expect <code>m!()</code> in <code>match … { m!(), _ =&gt; … }</code> to be seen as a match arm.</p>



<a name="225901555"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225901555" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225901555">(Feb 10 2021 at 20:23)</a>:</h4>
<p>we actually already do not know the expected AST kind of macro calls</p>



<a name="225901573"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225901573" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225901573">(Feb 10 2021 at 20:23)</a>:</h4>
<p>well, it depends on your POV to some extent</p>



<a name="225901624"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225901624" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225901624">(Feb 10 2021 at 20:23)</a>:</h4>
<p>but e.g. <code>fn foo() { bar!() }</code> could expand to an expression or a function item</p>



<a name="225901814"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225901814" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225901814">(Feb 10 2021 at 20:25)</a>:</h4>
<p>how does the compiler keep track of that? Is there a <code>ExprOrItem</code> production in the grammar for macro calls?</p>



<a name="225901889"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225901889" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225901889">(Feb 10 2021 at 20:25)</a>:</h4>
<p>Honestly I forget how it works</p>



<a name="225901910"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225901910" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225901910">(Feb 10 2021 at 20:25)</a>:</h4>
<p>I feel like there's some complexity around this in a few places</p>



<a name="225902015"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225902015" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225902015">(Feb 10 2021 at 20:26)</a>:</h4>
<p>I recall some ambiguity coming up with things like <code>fn foo() { bar!() &amp;&amp;true }</code></p>



<a name="225902109"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225902109" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225902109">(Feb 10 2021 at 20:26)</a>:</h4>
<p>or is a trailing semicolon sufficient to disambiguate there?</p>



<a name="225902145"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225902145" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225902145">(Feb 10 2021 at 20:27)</a>:</h4>
<p>maybe it only happens with <code>bar!{} &amp;&amp; true</code></p>



<a name="225902976"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225902976" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225902976">(Feb 10 2021 at 20:32)</a>:</h4>
<p>Oh fun, it looks like the delimiters are required to be different to make these compile:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">fn</span> <span class="nf">bar</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="fm">macro_rules!</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kc">false</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">foo1</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">impl</span><span class="w"> </span><span class="nb">Sized</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">item</span><span class="o">!</span><span class="p">{}</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="kc">true</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="k">fn</span> <span class="nf">foo2</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">impl</span><span class="w"> </span><span class="nb">Sized</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">expr</span><span class="o">!</span><span class="p">()</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="225904018"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225904018" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225904018">(Feb 10 2021 at 20:39)</a>:</h4>
<p>oh interesting, with a block around it things get confused for real. Is this a bug?</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">fn</span> <span class="nf">foo</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="kt">bool</span> <span class="p">{</span><span class="w"> </span><span class="p">{</span><span class="kc">false</span><span class="p">}</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="c1">// doesn't compile, parsed as two statements</span>
</code></pre></div>



<a name="225904440"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225904440" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225904440">(Feb 10 2021 at 20:42)</a>:</h4>
<p>oh nvm, the error message makes it clear this is deliberate</p>



<a name="225912726"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/macro%20invocations%20as%20match%20arms/near/225912726" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mara <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/macro.20invocations.20as.20match.20arms.html#225912726">(Feb 10 2021 at 21:40)</a>:</h4>
<blockquote>
<p>but e.g. <code>fn foo() { bar!() }</code> could expand to an expression or a function item</p>
</blockquote>
<p>which leads to the interesting case that <code>fn foo() { bar!{} bar!{} }</code> compiles fine even if <code>bar!{}</code> expands to <code>()</code> without a semicolon, because the parser already accepted it before it knew bar!{} was only an expression. (so, the output of <code>--pretty=expanded</code> doesn't even parse)</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>